/**
 * Copyright (C), 2015-2020, XXX有限公司
 * FileName: LearnMybatis
 * Author:   ZX
 * Date:     2020/7/18 19:37
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package org.example.LearnMybatis;

import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import org.apache.ibatis.transaction.TransactionFactory;
import org.aspectj.weaver.ast.Var;
import org.example.entity.Person;

import javax.servlet.annotation.WebFilter;
import java.lang.reflect.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author ZX
 * @create 2020/7/18
 * @since 1.0.0
 */

public class LearnMybatis {
    public static void main(String[] args) {
        TestUser testUser = (TestUser) Proxy.newProxyInstance(TestUser.class.getClassLoader(), new Class[]{TestUser.class},
                (proxy, method, args1) -> {
                    List<Person> list=new ArrayList<>();
                    //执行的方法
    //                System.out.println(method.getName());
                    //传递的参数
    //                System.out.println(Arrays.toString(args));
                    Map<String, Object> argNameMap = buildMethodArgNameMap(method, args1);
                    Select annotation = method.getAnnotation(Select.class);
                    if (annotation!=null){

                        //SQL
                        String sql = annotation.value()[0];
                        System.out.println(sql);
                        //解析后SQL
                        String parseSQL = parseSQL(sql, argNameMap);
                        System.out.println(parseSQL);
                        Class.forName("com.mysql.cj.jdbc.Driver");
                        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/learnssm?user=root&password=root&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false");
                        Statement statement = connection.createStatement();
                        ResultSet resultSet = statement.executeQuery(parseSQL);
                        while (resultSet.next()){
                            int id = resultSet.getInt(1);
                            String name = resultSet.getString(2);
                            list.add(new Person(id,name));
                        }

                    }
                    return list;
                });
        List<Person> list = testUser.selectUser(1, "\"zs\"");
        System.out.println(list.toString());
//        List<Person> list2=testUser.selectUserById(2);
//        System.out.println(list2.toString());
    }

    /**
     * 解析SQL
     * @param sql 要解析的SQL
     * @param argNameMap 参数的map
     * @return 解析后的SQL
     */
    public static String parseSQL(String sql,Map argNameMap){
        StringBuilder stringBuilder = new StringBuilder();
        int length = sql.length();
        for (int i = 0; i <length ; i++) {
            char c=sql.charAt(i);
            if(c=='#'){
                int nextIndex=i+1;
                char nextChar=sql.charAt(nextIndex);
                if(nextChar!='{'){
                    throw new RuntimeException(String.format("这里应该为#{\nsql:%s,near:%s\nindex:%d",
                            sql,sql.substring(nextIndex-1),nextIndex));
                }
                StringBuilder argSB=new StringBuilder();
                i=parseSQLArg(argSB,sql,nextIndex);
                String argName=argSB.toString();
                Object argValue = argNameMap.get(argName);
                if(argValue==null){
                    throw new RuntimeException(String.format("找不到参数:%s",
                            argSB.toString()));
                }
                stringBuilder.append(argValue.toString());
                continue;
            }
            stringBuilder.append(c);
        }
        return stringBuilder.toString();
    }

    /**
     * 解析参数
     * @param argSB 存放解析后的参数
     * @param sql SQL
     * @param nextIndex 准备解析的起始下标
     * @return 解析后的下标
     */
    private static int parseSQLArg(StringBuilder argSB, String sql, int nextIndex) {
        int start=nextIndex++-1;
        for (; nextIndex <sql.length() ; nextIndex++) {
            char c=sql.charAt(nextIndex);
            if(c!='}'){
                if(c=='#'){
                    throw new RuntimeException(String.format("缺少右括号:%s   index:%d",sql.substring(start),nextIndex));
                }
                argSB.append(c);
            }else
                return nextIndex;

        }
        throw new RuntimeException(String.format("缺少右括号\nindex:%d",nextIndex));
    }

    /**
     * 获取<方法参数,入参>的Map
     * @param method 方法
     * @param args 传入的参数
     * @return map
     */
    public static Map<String,Object> buildMethodArgNameMap(Method method, Object[] args){
        Map<String,Object> argNameMap=new HashMap<>();
        Parameter[] parameters = method.getParameters();
        int index=0;
        for (Parameter parameter : parameters) {
            argNameMap.put(parameter.getName(),args[index]);
            index++;
        }
        return argNameMap;
    }
}